import unittest

from google.appengine.api import memcache
from google.appengine.ext import ndb
from google.appengine.ext import testbed

from server_main import *
from game_history import *
from statistics.word_statistic import *

json_string = '''
{
    "rounds": [
        {
            "words": [
                {
                    "text": "Word1",
                    "owner": "Owner",
                    "result": "GUESS",
                    "time": 5.6
                },
                {
                    "text": "Word2",
                    "owner": "Owner",
                    "result": "GUESS",
                    "time": 10.6
                }
            ],
            "player1": "Player_1",
            "player2": "Player_2"
        }
    ],
    "game_type": "CROCODILE"
}
'''

json_string_1 = '''
{
    "rounds": [
        {
            "words": [
                {
                    "text": "Word1",
                    "owner": "Owner",
                    "result": "PUT_BACK",
                    "time": 1.6
                },
                {
                    "text": "Word1",
                    "owner": "Owner",
                    "result": "FAIL",
                    "time": 5.6
                },
                {
                    "text": "Word2",
                    "owner": "Owner",
                    "result": "PUT_BACK",
                    "time": 11
                },
                {
                    "text": "Word",
                    "owner": "Owner",
                    "result": "TIME_OUT",
                    "time": 20
                }
            ],
            "player1": "Player_1",
            "player2": "Player_2"
        },
        {
            "words": [
                {
                    "text": "Word",
                    "owner": "Owner",
                    "result": "PUT_BACK",
                    "time": 5.6
                },
                {
                    "text": "Word",
                    "owner": "Owner",
                    "result": "FAIL",
                    "time": 18
                },
                {
                    "text": "Word2",
                    "owner": "Owner",
                    "result": "GUESS",
                    "time": 20
                }
            ],
            "player1": "Player_2",
            "player2": "Player_1"
        }
    ],
    "words_in_hat" : [
        {
            "owner" : "Vasya",
            "text" : "cat"
        },
        {
            "owner" : "Petya_LOH",
            "text" : "dog"
        },
        {
            "owner": "Owner",
            "text": "Word1"
        }
    ],
    "remote_id": 102
}
'''


class CGHTest(unittest.TestCase):
    def setUp(self):
        self.testbed = testbed.Testbed()
        self.testbed.activate()
        self.testbed.init_datastore_v3_stub()
        self.testbed.init_memcache_stub()

    def test_unused_words(self):
        self.game_history = json_to_game_history(json_string_1)
        self.assertEqual(frozenset(self.game_history.unused_words),
                         frozenset([Word(owner=self.game_history.players.
                                   index('Vasya'),
                                   text='cat'),
                                   Word(owner=self.game_history.
                                        players.index("Petya_LOH"),
                                        text="dog")]))

    def test_creation(self):
        self.game_history = json_to_game_history(json_string)
        self.assertEquals(sorted(self.game_history.players),
                          sorted(['Player_1', 'Player_2', 'Owner']))
        self.assertEquals(self.game_history.json_string, json_string)
        self.assertEquals(self.game_history.game_type, GameHistory.CROCODILE)

        round_ = Round()
        round_.player_guess = self.game_history.players.index("Player_2")
        round_.player_explain = self.game_history.players.index("Player_1")
        round_.duration_time = -1
        self.assertEqual(self.game_history.rounds, [round_])

        word_1 = Word()
        word_2 = Word()
        word_1.text = "Word1"
        word_2.text = "Word2"
        word_1.owner = self.game_history.players.index("Owner")
        word_2.owner = self.game_history.players.index("Owner")
        self.assertEqual(set(self.game_history.words), set([word_1, word_2]))

        guess_result = WordGuessResult()
        guess_result.result = WordGuessResult.GUESS
        guess_result.time_sec = 5.6
        guess_result.round_ = 0
        guess_result.word = self.game_history.words.index(word_1)
        guess_result2 = WordGuessResult()
        guess_result2.result = WordGuessResult.GUESS
        guess_result2.time_sec = 10.6
        guess_result2.round_ = 0
        guess_result2.word = self.game_history.words.index(word_2)
        self.assertEqual(self.game_history.guess_results,
                         [guess_result, guess_result2])

    def test_id(self):
        self.game_history = json_to_game_history(json_string_1)
        self.assertEqual(self.game_history.id_.id_, 102)
        self.assertEqual(self.game_history.id_.game_local, False)
        self.assertEquals(self.game_history.game_type,
                          GameHistory.HAT_STANDART)

    def test_no_id(self):
        self.game_history = json_to_game_history(json_string)
        self.assertEqual(self.game_history.id_.id_, hash(json_string))
        self.assertEqual(self.game_history.id_.game_local, True)

    def test_statistic_adding(self):
        self.game_history = json_to_game_history(json_string)
        self.game_history.game_type = GameHistory.HAT_STANDART
        self.game_history.add_to_statistic()
        self.assertEqual(len(list(WordStatistic.query())), 2)
        self.assertEqual(len(list(WordStatistic.query().filter(
            WordStatistic.word == 'Word1'))), 1)
        self.assertEqual(len(list(WordStatistic.query().filter(
            WordStatistic.word == 'Word2'))), 1)
        word_stat_1 = WordStatistic.query().filter(
            WordStatistic.word == 'Word1').get()
        word_stat_2 = WordStatistic.query().filter(
            WordStatistic.word == 'Word2').get()
        self.assertEqual(word_stat_1.word, "Word1")
        self.assertEqual(word_stat_2.word, "Word2")
        self.assertEqual(len(word_stat_1.hist_ttime), 1)
        self.assertEqual(len(word_stat_2.hist_ttime), 1)
        self.assertEqual(word_stat_1.hist_ttime[0], TTimeToCnt(time_sec=6,
                                                               cnt_guess=1))
        self.assertEqual(word_stat_2.hist_ttime[0], TTimeToCnt(time_sec=5,
                                                               cnt_guess=1))

        self.assertEqual(len(word_stat_1.hist_ltime_nattempt), 1)
        self.assertEqual(len(word_stat_2.hist_ltime_nattempt), 1)
        self.assertEqual(word_stat_1.hist_ltime_nattempt[0],
                         LTimeAttemptNToCnt(time_sec=6, cnt_guess=1,
                                            num_attempts=1))
        self.assertEqual(word_stat_2.hist_ltime_nattempt[0],
                         LTimeAttemptNToCnt(time_sec=5, cnt_guess=1,
                                            num_attempts=1))

        self.game_history = json_to_game_history(json_string_1)
        self.game_history.add_to_statistic()
        self.assertEqual(len(list(WordStatistic.query())), 3)
        self.assertEqual(len(list(WordStatistic.query().filter(
            WordStatistic.word == 'Word1'))), 1)
        self.assertEqual(len(list(WordStatistic.query().filter(
            WordStatistic.word == 'Word2'))), 1)
        self.assertEqual(len(list(WordStatistic.query().filter(
            WordStatistic.word == 'Word'))), 1)
        word_stat_1 = WordStatistic.query().filter(
            WordStatistic.word == 'Word1').get()
        word_stat_2 = WordStatistic.query().filter(
            WordStatistic.word == 'Word2').get()
        word_stat_0 = WordStatistic.query().filter(
            WordStatistic.word == 'Word').get()

        self.assertEqual(len(word_stat_1.hist_ttime), 1)
        self.assertEqual(len(word_stat_2.hist_ttime), 2)
        self.assertEqual(len(word_stat_0.hist_ttime), 1)
        self.assertEqual(word_stat_1.hist_ttime[0],
                         TTimeToCnt(time_sec=6, cnt_guess=1, cnt_fail=1))
        self.assertEqual(word_stat_2.hist_ttime[0], TTimeToCnt(time_sec=5,
                                                               cnt_guess=1))
        self.assertEqual(word_stat_2.hist_ttime[1], TTimeToCnt(time_sec=8,
                                                               cnt_guess=1))
        self.assertEqual(word_stat_0.hist_ttime[0], TTimeToCnt(time_sec=27,
                                                               cnt_fail=1))

        self.assertEqual(len(word_stat_1.hist_ltime_nattempt), 2)
        self.assertEqual(len(word_stat_2.hist_ltime_nattempt), 2)
        self.assertEqual(len(word_stat_0.hist_ltime_nattempt), 1)
        self.assertEqual(word_stat_1.hist_ltime_nattempt[0],
                         LTimeAttemptNToCnt(time_sec=6, cnt_guess=1,
                                            num_attempts=1))
        self.assertEqual(word_stat_1.hist_ltime_nattempt[1],
                         LTimeAttemptNToCnt(time_sec=4, cnt_fail=1,
                                            num_attempts=2))
        self.assertEqual(word_stat_2.hist_ltime_nattempt[0],
                         LTimeAttemptNToCnt(time_sec=5, cnt_guess=1,
                                            num_attempts=1))
        self.assertEqual(word_stat_2.hist_ltime_nattempt[1],
                         LTimeAttemptNToCnt(time_sec=2, cnt_guess=1,
                                            num_attempts=2))
        self.assertEqual(word_stat_0.hist_ltime_nattempt[0],
                         LTimeAttemptNToCnt(time_sec=13, cnt_fail=1,
                                            num_attempts=3))

    def tearDown(self):
        self.testbed.deactivate()


if __name__ == '__main__':
    unittest.main()
